<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LibreTV 播放器</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="css/styles.css">
    <style>
        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: #0f1622;
            color: white;
        }
        .player-container {
            width: 100%;
            max-width: 1200px;
            margin: 0 auto;
        }
        #player {
            width: 100%;
            height: 60vh; /* 视频播放器高度 */
        }
        .loading-container {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            background-color: rgba(0, 0, 0, 0.7);
            color: white;
            z-index: 100;
            flex-direction: column;
        }
        .loading-spinner {
            width: 50px;
            height: 50px;
            border: 4px solid rgba(255, 255, 255, 0.3);
            border-radius: 50%;
            border-top-color: white;
            animation: spin 1s ease-in-out infinite;
            margin-bottom: 10px;
        }
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
        .error-container {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            display: none;
            align-items: center;
            justify-content: center;
            background-color: rgba(0, 0, 0, 0.7);
            color: white;
            z-index: 100;
            flex-direction: column;
            text-align: center;
            padding: 1rem;
        }
        .error-icon {
            font-size: 48px;
            margin-bottom: 10px;
        }
        .episode-active {
            background-color: #3b82f6 !important;
            border-color: #60a5fa !important;
        }
        .episode-grid {
            max-height: 30vh;
            overflow-y: auto;
            padding: 1rem 0;
        }
        .switch {
            position: relative;
            display: inline-block;
            width: 46px;
            height: 24px;
        }
        .switch input {
            opacity: 0;
            width: 0;
            height: 0;
        }
        .slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #333;
            transition: .4s;
            border-radius: 24px;
        }
        .slider:before {
            position: absolute;
            content: "";
            height: 18px;
            width: 18px;
            left: 3px;
            bottom: 3px;
            background-color: white;
            transition: .4s;
            border-radius: 50%;
        }
        input:checked + .slider {
            background-color: #00ccff;
        }
        input:checked + .slider:before {
            transform: translateX(22px);
        }
        /* 添加快捷键提示样式 */
        .shortcut-hint {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 1rem 2rem;
            border-radius: 0.5rem;
            font-size: 1.5rem;
            display: flex;
            align-items: center;
            gap: 0.5rem;
            z-index: 1000;
            opacity: 0;
            transition: opacity 0.3s ease;
        }
        .shortcut-hint.show {
            opacity: 1;
        }
    </style>
</head>
<body>
    <header class="bg-[#111] p-4 flex justify-between items-center border-b border-[#333]">
        <div class="flex items-center">
            <a href="index.html" class="flex items-center">
                <svg class="w-8 h-8 mr-2 text-[#00ccff]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
                </svg>
                <h1 class="text-xl font-bold gradient-text">LibreTV</h1>
            </a>
        </div>
        <h2 id="videoTitle" class="text-xl font-semibold truncate flex-1 text-center"></h2>
        <a href="index.html" class="px-4 py-2 bg-[#222] hover:bg-[#333] border border-[#333] rounded-lg transition-colors">
            返回首页
        </a>
    </header>

    <main class="container mx-auto px-4 py-4">
        <!-- 视频播放区 -->
        <div class="player-container">
            <div class="relative">
                <div id="player"></div>
                <div class="loading-container" id="loading">
                    <div class="loading-spinner"></div>
                    <div>正在加载视频...</div>
                </div>
                <div class="error-container" id="error">
                    <div class="error-icon">⚠️</div>
                    <div id="error-message">视频加载失败</div>
                    <div style="margin-top: 10px; font-size: 14px; color: #aaa;">请尝试其他视频源或稍后重试</div>
                </div>
            </div>
        </div>

        <!-- 集数导航 -->
        <div class="player-container">
            <div class="flex justify-between items-center my-4">
                <button onclick="playPreviousEpisode()" id="prevButton" class="px-4 py-2 bg-[#222] hover:bg-[#333] border border-[#333] rounded-lg transition-colors">
                    <svg class="w-5 h-5 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
                    </svg>
                    上一集
                </button>
                <span class="text-gray-400" id="episodeInfo">加载中...</span>
                <button onclick="playNextEpisode()" id="nextButton" class="px-4 py-2 bg-[#222] hover:bg-[#333] border border-[#333] rounded-lg transition-colors">
                    下一集
                    <svg class="w-5 h-5 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
                    </svg>
                </button>
            </div>
        </div>

        <!-- 添加自动播放开关和排序按钮 -->
        <div class="player-container">
            <div class="flex justify-end items-center mb-4 gap-2">
                <span class="text-gray-400 text-sm">自动连播</span>
                <label class="switch">
                    <input type="checkbox" id="autoplayToggle">
                    <span class="slider"></span>
                </label>
                <button onclick="toggleEpisodeOrder()" class="ml-4 px-4 py-2 bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 text-white font-semibold rounded-full shadow-lg hover:shadow-xl transition-all duration-300 flex items-center justify-center space-x-2">
                    <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" id="orderIcon" viewBox="0 0 20 20" fill="currentColor">
                        <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11a1 1 0 10-2 0v3.586L7.707 9.293a1 1 0 00-1.414 1.414l3 3a1 1 0 001.414 0l3-3a1 1 0 00-1.414-1.414L11 10.586V7z" clip-rule="evenodd" />
                    </svg>
                    <span id="orderText">倒序排列</span>
                </button>
            </div>
        </div>

        <!-- 集数网格 -->
        <div class="player-container">
            <div class="episode-grid" id="episodesGrid">
                <div class="grid grid-cols-2 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8 gap-2" id="episodesList">
                    <!-- 集数将在这里动态加载 -->
                    <div class="col-span-full text-center text-gray-400 py-8">加载中...</div>
                </div>
            </div>
        </div>
    </main>

    <!-- 添加快捷键提示元素 -->
    <div class="shortcut-hint" id="shortcutHint">
        <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" id="shortcutIcon">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
        </svg>
        <span id="shortcutText"></span>
    </div>

    <script src="https://s4.zstatic.net/ajax/libs/hls.js/1.5.6/hls.min.js" integrity="sha256-X1GmLMzVcTBRiGjEau+gxGpjRK96atNczcLBg5w6hKA=" crossorigin="anonymous"></script>
    <script src="https://s4.zstatic.net/ajax/libs/dplayer/1.26.0/DPlayer.min.js" integrity="sha256-OJg03lDZP0NAcl3waC9OT5jEa8XZ8SM2n081Ik953o4=" crossorigin="anonymous"></script>
    <script src="js/config.js"></script>
    <script>
        // 全局变量
        let currentVideoTitle = '';
        let currentEpisodeIndex = 0;
        let currentEpisodes = [];
        let episodesReversed = false;
        let dp = null;
        let currentHls = null; // 跟踪当前HLS实例
        let autoplayEnabled = true; // 默认开启自动连播
        let isUserSeeking = false; // 跟踪用户是否正在拖动进度条
        let videoHasEnded = false; // 跟踪视频是否已经自然结束
        let userClickedPosition = null; // 记录用户点击的位置
        let shortcutHintTimeout = null; // 用于控制快捷键提示显示时间
        let adFilteringEnabled = true; // 默认开启广告过滤

        // 页面加载
        document.addEventListener('DOMContentLoaded', function() {
            // 解析URL参数
            const urlParams = new URLSearchParams(window.location.search);
            const videoUrl = urlParams.get('url');
            const title = urlParams.get('title');
            const index = parseInt(urlParams.get('index') || '0');

            // 从localStorage获取数据
            currentVideoTitle = title || localStorage.getItem('currentVideoTitle') || '未知视频';
            currentEpisodeIndex = index;
            
            // 设置自动连播开关状态
            autoplayEnabled = localStorage.getItem('autoplayEnabled') !== 'false'; // 默认为true
            document.getElementById('autoplayToggle').checked = autoplayEnabled;
            
            // 获取广告过滤设置
            adFilteringEnabled = localStorage.getItem(PLAYER_CONFIG.adFilteringStorage) !== 'false'; // 默认为true
            
            // 监听自动连播开关变化
            document.getElementById('autoplayToggle').addEventListener('change', function(e) {
                autoplayEnabled = e.target.checked;
                localStorage.setItem('autoplayEnabled', autoplayEnabled);
            });
            
            try {
                currentEpisodes = JSON.parse(localStorage.getItem('currentEpisodes') || '[]');
                episodesReversed = localStorage.getItem('episodesReversed') === 'true';
            } catch (e) {
                console.error('获取集数信息失败:', e);
                currentEpisodes = [];
                episodesReversed = false;
            }

            // 设置页面标题
            document.title = currentVideoTitle + ' - LibreTV播放器';
            document.getElementById('videoTitle').textContent = currentVideoTitle;
            
            // 初始化播放器
            if (videoUrl) {
                initPlayer(videoUrl);
            } else {
                showError('无效的视频链接');
            }

            // 更新集数信息
            updateEpisodeInfo();
            
            // 渲染集数列表
            renderEpisodes();
            
            // 更新按钮状态
            updateButtonStates();
            
            // 更新排序按钮状态
            updateOrderButton();

            // 添加对进度条的监听，确保点击准确跳转
            setTimeout(() => {
                setupProgressBarPreciseClicks();
            }, 1000);

            // 添加键盘快捷键事件监听
            document.addEventListener('keydown', handleKeyboardShortcuts);
        });

        // 处理键盘快捷键
        function handleKeyboardShortcuts(e) {
            // 忽略输入框中的按键事件
            if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;

            // Alt + 左箭头 = 上一集
            if (e.altKey && e.key === 'ArrowLeft') {
                if (currentEpisodeIndex > 0) {
                    playPreviousEpisode();
                    showShortcutHint('上一集', 'left');
                    e.preventDefault();
                }
            }
            
            // Alt + 右箭头 = 下一集
            if (e.altKey && e.key === 'ArrowRight') {
                if (currentEpisodeIndex < currentEpisodes.length - 1) {
                    playNextEpisode();
                    showShortcutHint('下一集', 'right');
                    e.preventDefault();
                }
            }
        }

        // 显示快捷键提示
        function showShortcutHint(text, direction) {
            const hintElement = document.getElementById('shortcutHint');
            const textElement = document.getElementById('shortcutText');
            const iconElement = document.getElementById('shortcutIcon');
            
            // 清除之前的超时
            if (shortcutHintTimeout) {
                clearTimeout(shortcutHintTimeout);
            }
            
            // 设置文本和图标方向
            textElement.textContent = text;
            
            if (direction === 'left') {
                iconElement.innerHTML = '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>';
            } else {
                iconElement.innerHTML = '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>';
            }
            
            // 显示提示
            hintElement.classList.add('show');
            
            // 两秒后隐藏
            shortcutHintTimeout = setTimeout(() => {
                hintElement.classList.remove('show');
            }, 2000);
        }

        // 初始化播放器
        function initPlayer(videoUrl) {
            if (!videoUrl) return;

            // 配置HLS.js选项
            const hlsConfig = {
                debug: false,
                loader: adFilteringEnabled ? CustomHlsJsLoader : Hls.DefaultConfig.loader,
                enableWorker: true,
                lowLatencyMode: false,
                backBufferLength: 90,
                maxBufferLength: 30,
                maxMaxBufferLength: 60,
                maxBufferSize: 30 * 1000 * 1000,
                maxBufferHole: 0.5,
                fragLoadingMaxRetry: 6,
                fragLoadingMaxRetryTimeout: 64000,
                fragLoadingRetryDelay: 1000,
                manifestLoadingMaxRetry: 3,
                manifestLoadingRetryDelay: 1000,
                levelLoadingMaxRetry: 4,
                levelLoadingRetryDelay: 1000,
                startLevel: -1,
                abrEwmaDefaultEstimate: 500000,
                abrBandWidthFactor: 0.95,
                abrBandWidthUpFactor: 0.7,
                abrMaxWithRealBitrate: true,
                stretchShortVideoTrack: true,
                appendErrorMaxRetry: 5,  // 增加尝试次数
                liveSyncDurationCount: 3,
                liveDurationInfinity: false
            };
            
            // 创建DPlayer实例
            dp = new DPlayer({
                container: document.getElementById('player'),
                autoplay: true,
                theme: '#00ccff',
                preload: 'auto',
                loop: false,
                lang: 'zh-cn',
                hotkey: true,        // 启用键盘控制，包括空格暂停/播放、方向键控制进度和音量
                mutex: true,
                volume: 0.7,
                screenshot: true,                // 启用截图功能
                preventClickToggle: false,       // 允许点击视频切换播放/暂停
                airplay: true,                   // 在Safari中启用AirPlay功能
                chromecast: true,                // 启用Chromecast投屏功能
                contextmenu: [                   // 自定义右键菜单
                    {
                        text: '关于 LibreTV',
                        link: 'https://github.com/bestzwei/LibreTV'
                    },
                    {
                        text: '问题反馈',
                        click: (player) => {
                            window.open('https://github.com/bestzwei/LibreTV/issues', '_blank');
                        }
                    }
                ],
                video: {
                    url: videoUrl,
                    type: 'hls',
                    pic: 'https://img.picgo.net/2025/04/12/image362e7d38b4af4a74.png', // 设置视频封面图
                    customType: {
                        hls: function(video, player) {
                            // 清理之前的HLS实例
                            if (currentHls && currentHls.destroy) {
                                try {
                                    currentHls.destroy();
                                } catch (e) {
                                    console.warn('销毁旧HLS实例出错:', e);
                                }
                            }
                            
                            // 创建新的HLS实例
                            const hls = new Hls(hlsConfig);
                            currentHls = hls;
                            
                            // 跟踪是否已经显示错误
                            let errorDisplayed = false;
                            // 跟踪是否有错误发生
                            let errorCount = 0;
                            // 跟踪视频是否开始播放
                            let playbackStarted = false;
                            // 跟踪视频是否出现bufferAppendError
                            let bufferAppendErrorCount = 0;
                            
                            // 监听视频播放事件
                            video.addEventListener('playing', function() {
                                playbackStarted = true;
                                document.getElementById('loading').style.display = 'none';
                                document.getElementById('error').style.display = 'none';
                            });
                            
                            // 监听视频进度事件
                            video.addEventListener('timeupdate', function() {
                                if (video.currentTime > 1) {
                                    // 视频进度超过1秒，隐藏错误（如果存在）
                                    document.getElementById('error').style.display = 'none';
                                }
                            });
                            
                            hls.loadSource(video.src);
                            hls.attachMedia(video);
                            
                            hls.on(Hls.Events.MANIFEST_PARSED, function() {
                                video.play().catch(e => {
                                    console.warn('自动播放被阻止:', e);
                                });
                            });
                            
                            hls.on(Hls.Events.ERROR, function(event, data) {
                                console.log('HLS事件:', event, '数据:', data);
                                
                                // 增加错误计数
                                errorCount++;
                                
                                // 处理bufferAppendError
                                if (data.details === 'bufferAppendError') {
                                    bufferAppendErrorCount++;
                                    console.warn(`bufferAppendError 发生 ${bufferAppendErrorCount} 次`);
                                    
                                    // 如果视频已经开始播放，则忽略这个错误
                                    if (playbackStarted) {
                                        console.log('视频已在播放中，忽略bufferAppendError');
                                        return;
                                    }
                                    
                                    // 如果出现多次bufferAppendError但视频未播放，尝试恢复
                                    if (bufferAppendErrorCount >= 3) {
                                        hls.recoverMediaError();
                                    }
                                }
                                
                                // 如果是致命错误，且视频未播放
                                if (data.fatal && !playbackStarted) {
                                    console.error('致命HLS错误:', data);
                                    
                                    // 尝试恢复错误
                                    switch(data.type) {
                                        case Hls.ErrorTypes.NETWORK_ERROR:
                                            console.log("尝试恢复网络错误");
                                            hls.startLoad();
                                            break;
                                        case Hls.ErrorTypes.MEDIA_ERROR:
                                            console.log("尝试恢复媒体错误");
                                            hls.recoverMediaError();
                                            break;
                                        default:
                                            // 仅在多次恢复尝试后显示错误
                                            if (errorCount > 3 && !errorDisplayed) {
                                                errorDisplayed = true;
                                                showError('视频加载失败，可能是格式不兼容或源不可用');
                                            }
                                            break;
                                    }
                                }
                            });
                            
                            // 监听分段加载事件
                            hls.on(Hls.Events.FRAG_LOADED, function() {
                                document.getElementById('loading').style.display = 'none';
                            });
                            
                            // 监听级别加载事件
                            hls.on(Hls.Events.LEVEL_LOADED, function() {
                                document.getElementById('loading').style.display = 'none';
                            });
                        }
                    }
                }
            });

            dp.on('loadedmetadata', function() {
                document.getElementById('loading').style.display = 'none';
                videoHasEnded = false; // 视频加载时重置结束标志
                
                // 视频加载完成后重新设置进度条点击监听
                setupProgressBarPreciseClicks();
                
                // 视频加载成功后，在稍微延迟后将其添加到观看历史
                setTimeout(saveToHistory, 3000);
            });

            dp.on('error', function() {
                // 检查视频是否已经在播放
                if (dp.video && dp.video.currentTime > 1) {
                    console.log('发生错误，但视频已在播放中，忽略');
                    return;
                }
                showError('视频播放失败，请检查视频源或网络连接');
            });
            
            // 添加seeking和seeked事件监听器，以检测用户是否在拖动进度条
            dp.on('seeking', function() {
                isUserSeeking = true;
                videoHasEnded = false; // 重置视频结束标志
                
                // 如果是用户通过点击进度条设置的位置，确保准确跳转
                if (userClickedPosition !== null && dp.video) {
                    // 确保用户的点击位置被正确应用，避免自动跳至视频末尾
                    const clickedTime = userClickedPosition;
                    
                    // 防止跳转到视频结尾
                    if (Math.abs(dp.video.duration - clickedTime) < 0.5) {
                        // 如果点击的位置非常接近结尾，稍微减少一点时间
                        dp.video.currentTime = Math.max(0, clickedTime - 0.5);
                    } else {
                        dp.video.currentTime = clickedTime;
                    }
                    
                    // 清除记录的位置
                    setTimeout(() => {
                        userClickedPosition = null;
                    }, 200);
                }
            });
            
            // 改进seeked事件处理
            dp.on('seeked', function() {
                // 如果视频跳转到了非常接近结尾的位置(小于0.3秒)，且不是自然播放到此处
                if (dp.video && dp.video.duration > 0) {
                    const timeFromEnd = dp.video.duration - dp.video.currentTime;
                    if (timeFromEnd < 0.3 && isUserSeeking) {
                        // 将播放时间往回移动一点点，避免触发结束事件
                        dp.video.currentTime = Math.max(0, dp.video.currentTime - 1);
                    }
                }
                
                // 延迟重置seeking标志，以便于区分自然播放结束和用户拖拽
                setTimeout(() => {
                    isUserSeeking = false;
                }, 200);
            });
            
            // 修改视频结束事件监听器，添加额外检查
            dp.on('ended', function() {
                videoHasEnded = true; // 标记视频已自然结束
                
                // 如果启用了自动连播，并且有下一集可播放，则自动播放下一集
                if (autoplayEnabled && currentEpisodeIndex < currentEpisodes.length - 1) {
                    console.log('视频播放结束，自动播放下一集');
                    // 稍长延迟以确保所有事件处理完成
                    setTimeout(() => {
                        // 确认不是因为用户拖拽导致的假结束事件
                        if (videoHasEnded && !isUserSeeking) {
                            playNextEpisode();
                            videoHasEnded = false; // 重置标志
                        }
                    }, 1000);
                } else {
                    console.log('视频播放结束，无下一集或未启用自动连播');
                }
            });
            
            // 添加事件监听以检测近视频末尾的点击拖动
            dp.on('timeupdate', function() {
                if (dp.video && dp.duration > 0) {
                    // 如果视频接近结尾但不是自然播放到结尾，重置自然结束标志
                    if (isUserSeeking && dp.video.currentTime > dp.video.duration * 0.95) {
                        videoHasEnded = false;
                    }
                }
            });
            
            // 10秒后如果仍在加载，但不立即显示错误
            setTimeout(function() {
                // 如果视频已经播放开始，则不显示错误
                if (dp && dp.video && dp.video.currentTime > 0) {
                    return;
                }
                
                if (document.getElementById('loading').style.display !== 'none') {
                    document.getElementById('loading').innerHTML = `
                        <div class="loading-spinner"></div>
                        <div>视频加载时间较长，请耐心等待...</div>
                        <div style="font-size: 12px; color: #aaa; margin-top: 10px;">如长时间无响应，请尝试其他视频源</div>
                    `;
                }
            }, 10000);
        }

        // 自定义M3U8 Loader用于过滤广告
        class CustomHlsJsLoader extends Hls.DefaultConfig.loader {
            constructor(config) {
                super(config);
                const load = this.load.bind(this);
                this.load = function(context, config, callbacks) {
                    // 拦截manifest和level请求
                    if (context.type === 'manifest' || context.type === 'level') {
                        const onSuccess = callbacks.onSuccess;
                        callbacks.onSuccess = function(response, stats, context) {
                            // 如果是m3u8文件，处理内容以移除广告分段
                            if (response.data && typeof response.data === 'string') {
                                // 过滤掉广告段 - 实现更精确的广告过滤逻辑
                                response.data = filterAdsFromM3U8(response.data, true);
                            }
                            return onSuccess(response, stats, context);
                        };
                    }
                    // 执行原始load方法
                    load(context, config, callbacks);
                };
            }
        }

        // M3U8清单广告过滤函数
        function filterAdsFromM3U8(m3u8Content, strictMode = false) {
            if (!m3u8Content) return '';
            
            // 按行分割M3U8内容
            const lines = m3u8Content.split('\n');
            const filteredLines = [];
            
            for (let i = 0; i < lines.length; i++) {
                const line = lines[i];
                
                // 只过滤#EXT-X-DISCONTINUITY标识
                if (!line.includes('#EXT-X-DISCONTINUITY')) {
                    filteredLines.push(line);
                }
            }
            
            return filteredLines.join('\n');
        }

        // 显示错误
        function showError(message) {
            // 在视频已经播放的情况下不显示错误
            if (dp && dp.video && dp.video.currentTime > 1) {
                console.log('忽略错误:', message);
                return;
            }
            
            document.getElementById('loading').style.display = 'none';
            document.getElementById('error').style.display = 'flex';
            document.getElementById('error-message').textContent = message;
        }

        // 更新集数信息
        function updateEpisodeInfo() {
            if (currentEpisodes.length > 0) {
                document.getElementById('episodeInfo').textContent = `第 ${currentEpisodeIndex + 1}/${currentEpisodes.length} 集`;
            } else {
                document.getElementById('episodeInfo').textContent = '无集数信息';
            }
        }

        // 更新按钮状态
        function updateButtonStates() {
            const prevButton = document.getElementById('prevButton');
            const nextButton = document.getElementById('nextButton');
            
            // 处理上一集按钮
            if (currentEpisodeIndex > 0) {
                prevButton.classList.remove('bg-gray-700', 'cursor-not-allowed');
                prevButton.classList.add('bg-[#222]', 'hover:bg-[#333]');
                prevButton.removeAttribute('disabled');
            } else {
                prevButton.classList.add('bg-gray-700', 'cursor-not-allowed');
                prevButton.classList.remove('bg-[#222]', 'hover:bg-[#333]');
                prevButton.setAttribute('disabled', '');
            }
            
            // 处理下一集按钮
            if (currentEpisodeIndex < currentEpisodes.length - 1) {
                nextButton.classList.remove('bg-gray-700', 'cursor-not-allowed');
                nextButton.classList.add('bg-[#222]', 'hover:bg-[#333]');
                nextButton.removeAttribute('disabled');
            } else {
                nextButton.classList.add('bg-gray-700', 'cursor-not-allowed');
                nextButton.classList.remove('bg-[#222]', 'hover:bg-[#333]');
                nextButton.setAttribute('disabled', '');
            }
        }

        // 渲染集数按钮
        function renderEpisodes() {
            const episodesList = document.getElementById('episodesList');
            if (!episodesList) return;
            
            if (!currentEpisodes || currentEpisodes.length === 0) {
                episodesList.innerHTML = '<div class="col-span-full text-center text-gray-400 py-8">没有可用的集数</div>';
                return;
            }
            
            const episodes = episodesReversed ? [...currentEpisodes].reverse() : currentEpisodes;
            let html = '';
            
            episodes.forEach((episode, index) => {
                // 根据倒序状态计算真实的剧集索引
                const realIndex = episodesReversed ? currentEpisodes.length - 1 - index : index;
                const isActive = realIndex === currentEpisodeIndex;
                
                html += `
                    <button id="episode-${realIndex}" 
                            onclick="playEpisode(${realIndex})" 
                            class="px-4 py-2 ${isActive ? 'episode-active' : 'bg-[#222] hover:bg-[#333]'} border ${isActive ? 'border-blue-500' : 'border-[#333]'} rounded-lg transition-colors text-center episode-btn">
                        第${realIndex + 1}集
                    </button>
                `;
            });
            
            episodesList.innerHTML = html;
        }

        // 播放指定集数
        function playEpisode(index) {
            if (index < 0 || index >= currentEpisodes.length) return;
            
            // 首先隐藏之前可能显示的错误
            document.getElementById('error').style.display = 'none';
            // 显示加载指示器
            document.getElementById('loading').style.display = 'flex';
            document.getElementById('loading').innerHTML = `
                <div class="loading-spinner"></div>
                <div>正在加载视频...</div>
            `;
            
            const url = currentEpisodes[index];
            currentEpisodeIndex = index;
            videoHasEnded = false; // 重置视频结束标志
            
            // 更新URL，不刷新页面
            const newUrl = new URL(window.location.href);
            newUrl.searchParams.set('index', index);
            newUrl.searchParams.set('url', url);
            window.history.pushState({}, '', newUrl);
            
            // 更新播放器
            if (dp) {
                try {
                    dp.switchVideo({
                        url: url,
                        type: 'hls'
                    });
                    
                    // 确保播放开始
                    const playPromise = dp.play();
                    if (playPromise !== undefined) {
                        playPromise.catch(error => {
                            console.warn('播放失败，尝试重新初始化:', error);
                            // 如果切换视频失败，重新初始化播放器
                            initPlayer(url);
                        });
                    }
                } catch (e) {
                    console.error('切换视频出错，尝试重新初始化:', e);
                    // 如果出错，重新初始化播放器
                    initPlayer(url);
                }
            } else {
                initPlayer(url);
            }
            
            // 更新UI
            updateEpisodeInfo();
            updateButtonStates();
            renderEpisodes();

            // 重置用户点击位置记录
            userClickedPosition = null;
        }

        // 播放上一集
        function playPreviousEpisode() {
            if (currentEpisodeIndex > 0) {
                playEpisode(currentEpisodeIndex - 1);
            }
        }

        // 播放下一集
        function playNextEpisode() {
            if (currentEpisodeIndex < currentEpisodes.length - 1) {
                playEpisode(currentEpisodeIndex + 1);
            }
        }

        // 切换集数排序
        function toggleEpisodeOrder() {
            episodesReversed = !episodesReversed;
            
            // 保存到localStorage
            localStorage.setItem('episodesReversed', episodesReversed);
            
            // 重新渲染集数列表
            renderEpisodes();
            
            // 更新排序按钮
            updateOrderButton();
        }

        // 更新排序按钮状态
        function updateOrderButton() {
            const orderText = document.getElementById('orderText');
            const orderIcon = document.getElementById('orderIcon');
            
            if (orderText && orderIcon) {
                orderText.textContent = episodesReversed ? '正序排列' : '倒序排列';
                orderIcon.style.transform = episodesReversed ? 'rotate(180deg)' : '';
            }
        }

        // 设置进度条准确点击处理
        function setupProgressBarPreciseClicks() {
            // 查找DPlayer的进度条元素
            const progressBar = document.querySelector('.dplayer-bar-wrap');
            if (!progressBar || !dp || !dp.video) return;
            
            // 移除可能存在的旧事件监听器
            progressBar.removeEventListener('mousedown', handleProgressBarClick);
            
            // 添加新的事件监听器
            progressBar.addEventListener('mousedown', handleProgressBarClick);
            
            // 在移动端也添加触摸事件支持
            progressBar.removeEventListener('touchstart', handleProgressBarTouch);
            progressBar.addEventListener('touchstart', handleProgressBarTouch);
            
            console.log('进度条精确点击监听器已设置');
        }

        // 处理进度条点击
        function handleProgressBarClick(e) {
            if (!dp || !dp.video) return;
            
            // 计算点击位置相对于进度条的比例
            const rect = e.currentTarget.getBoundingClientRect();
            const percentage = (e.clientX - rect.left) / rect.width;
            
            // 计算点击位置对应的视频时间
            const duration = dp.video.duration;
            let clickTime = percentage * duration;
            
            // 处理视频接近结尾的情况
            if (duration - clickTime < 1) {
                // 如果点击位置非常接近结尾，稍微往前移一点
                clickTime = Math.min(clickTime, duration - 1.5);
                console.log(`进度条点击接近结尾，调整时间为 ${clickTime.toFixed(2)}/${duration.toFixed(2)}`);
            }
            
            // 记录用户点击的位置
            userClickedPosition = clickTime;
            
            // 输出调试信息
            console.log(`进度条点击: ${percentage.toFixed(4)}, 时间: ${clickTime.toFixed(2)}/${duration.toFixed(2)}`);
            
            // 阻止默认事件传播，避免DPlayer内部逻辑将视频跳至末尾
            e.stopPropagation();
            
            // 直接设置视频时间
            dp.seek(clickTime);
        }

        // 处理移动端触摸事件
        function handleProgressBarTouch(e) {
            if (!dp || !dp.video || !e.touches[0]) return;
            
            const touch = e.touches[0];
            const rect = e.currentTarget.getBoundingClientRect();
            const percentage = (touch.clientX - rect.left) / rect.width;
            
            const duration = dp.video.duration;
            let clickTime = percentage * duration;
            
            // 处理视频接近结尾的情况
            if (duration - clickTime < 1) {
                clickTime = Math.min(clickTime, duration - 1.5);
            }
            
            // 记录用户点击的位置
            userClickedPosition = clickTime;
            
            console.log(`进度条触摸: ${percentage.toFixed(4)}, 时间: ${clickTime.toFixed(2)}/${duration.toFixed(2)}`);
            
            e.stopPropagation();
            dp.seek(clickTime);
        }
        
        // 在播放器初始化后添加视频到历史记录
        function saveToHistory() {
            // 尝试从URL中获取参数
            const urlParams = new URLSearchParams(window.location.search);
            const sourceName = urlParams.get('source') || '';

            // 构建要保存的视频信息对象
            const videoInfo = {
                title: currentVideoTitle,
                url: window.location.href, // 保存完整URL以便能直接打开
                episodeIndex: currentEpisodeIndex,
                sourceName: sourceName,
                timestamp: Date.now()
            };
            
            // 如果外部定义了addToViewingHistory函数，则调用它
            if (typeof addToViewingHistory === 'function') {
                addToViewingHistory(videoInfo);
            } else {
                // 否则直接使用本地实现
                try {
                    const history = JSON.parse(localStorage.getItem('viewingHistory') || '[]');
                    
                    // 检查是否已经存在相同的项目
                    const existingIndex = history.findIndex(item => item.url === videoInfo.url);
                    if (existingIndex !== -1) {
                        history.splice(existingIndex, 1);
                    }
                    
                    // 添加新记录到最前面
                    history.unshift(videoInfo);
                    
                    // 限制历史记录数量为50条
                    if (history.length > 50) history.splice(50);
                    
                    localStorage.setItem('viewingHistory', JSON.stringify(history));
                } catch (e) {
                    console.error('保存观看历史失败:', e);
                }
            }
        }
    </script>
</body>
</html>
